#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "LPC23xx.h"
#include "bas_fun.h"
#include "uart_fun.h"
#include "net_fun.h"

//************************************************************************
#define N81 0         /* no   parity 8 bit  */
#define E71 1         /* even parity 7 bit  */
#define E81 2         /* even parity 8 bit  */
#define O71 3         /* ODD  parity 7 bit  PORT2  */
#define N71 4         /* no   parity 7 bit  PORT2  */
#define O81 5         /* ODD  parity 8 bit  */
#define N82 10        /* no   parity 8 bit stop 2 bit */
#define E82 11        /* even parity 8 bit stop 2 bit */
#define O82 12        /* odd  parity 8 bit stop 2 bit */

unsigned char uart_mode(char mode)
{
    unsigned char UnLCR;

	// UnLCR=>B10=>00=5Bit,01=6Bit,10=7Bit,11=8bit
	//        B2 =>0=1stop,1=2stop,
	//        B543=>001=Odd Parity,011=Even Parity,  B3=>0=Parity Dis,1=Parity Ena
	//        B7  =>0=Dis ,1=Ena  DLAB=Divisor Latch Access bit 
	UnLCR = 0x83;       // 8 bits, no Parity, 1 Stop bit      
	switch(mode) {
        case N81 : UnLCR=0x83; break;       // 0  no parity 8 bit  
        case E71 : UnLCR=0x9A; break;       // 1  even parity 7 bit  
        case E81 : UnLCR=0x9B; break;       // 2  even parity 8 bit 
        case O71 : UnLCR=0x8A; break;       // 3  odd  parity 7 bit 
        case N71 : UnLCR=0x82; break;       // 4  no   parity 7 bit  
        case O81 : UnLCR=0x8B; break;       // 5  odd  parity 8 bit 
        case N82 : UnLCR=0x87; break;       // 10 no   parity 8 bit stop 2 bit	
		case E82 : UnLCR=0x9F; break;       // 11 even parity 8 bit stop 2 bit	
		case O82 : UnLCR=0x8F; break;       // 12 odd  parity 8 bit stop 2 bit	
	}	
	return(UnLCR);
}

#ifdef UART0
void putch0(char c)
{
    while (!(U0LSR & 0x20));
    U0THR = c;
}

void int_uart0 (void) __irq 
{
    unsigned char c;

    if ((U0IIR & 0x0E) == 0x04) {        // Receive interrupt                   
       c = (char) U0RBR;                 // read character                      
       uart_rx_buf_write(0,c);
    }
                                         // Transmit interrupt  
	if (UART[0].tx_head!=UART[0].tx_tail) {
	   if ((U0LSR & 0x20))  U0THR=uart_tx_buf_read(0);
    }
	else {
	   if (UART[0].tx_int==1) UART[0].tx_int=2;
	}
    VICVectAddr = 0;                    // Acknowledge Interrupt   
}

void init_port0(int baud,char mode)
{
    unsigned char UnLCR;

	// PINSEL 00=Primary funtion , typically GPIO port  //
	// PINSEL 01=First  alternate funtion               //
	// PINSEL 10=Second alternate funtion               //
	// PINSEL 11=Third  alternate funtion               //
    PCONP   |= 0x00000008;
    PINSEL0 |= 0x00000050;  // Enable TxD1 RxD1   

	U0LCR = UnLCR = uart_mode(mode);    

    // U0DLL=(12000000/16/9600)%256=78.125
	// U0DLM=(12000000/16/9600)/256=0
	U0DLL=(CPU_HZ/16/baud)%256;
	U0DLM=(CPU_HZ/16/baud)/256;

    U0LCR = UnLCR&0x7F;                 /* DLAB = 0                            */
    U0IER = 0x03;                       /* Enable RDA and THRE interrupts      */

    VICVectAddr6  = (unsigned int)int_uart0;
    VICVectCntl6  = 6;               /* Interrupt -> Priority */
    VICIntEnable |= (1 << 6);           /* Interrupt -> Enable   */
  
    memset((char *)&UART[0],0,sizeof(UART_PARM));
	UART[0].rx_buf=(unsigned char *)URX_BUFF+0;
    UART[0].tx_buf=(unsigned char *)UTX_BUFF+0;
    UART[0].rx_max_buf=URX_LEN0;
    UART[0].tx_max_buf=UTX_LEN0;
    uart_rts_dis(0);
}
#endif


#ifdef UART1

void putch1(char c)
{
    while (!(U1LSR & 0x20));
    U1THR = c;
}

void int_uart1 (void) __irq 
{
    unsigned char c;

    if ((U1IIR & 0x0E) == 0x04) {        // Receive interrupt                   
       c = (char) U1RBR;                 // read character                      
       uart_rx_buf_write(1,c);
    }
                                         // Transmit interrupt  
	if (UART[1].tx_head!=UART[1].tx_tail) {
	   if ((U1LSR & 0x20))  U1THR=uart_tx_buf_read(1);
    }
	else {
	   if (UART[1].tx_int==1) UART[1].tx_int=2;
	}
    VICVectAddr = 0;                    // Acknowledge Interrupt   
}

void init_port1(int baud,char mode)
{
    unsigned char UnLCR;
	
    PCONP   |= 0x00000010;
	// PINSEL 00=Primary funtion , typically GPIO port  //
	// PINSEL 01=First  alternate funtion               //
	// PINSEL 10=Second alternate funtion               //
	// PINSEL 11=Third  alternate funtion               //

	PINSEL0 |= 0x40000000;  // Enable TxD1 //
	PINSEL1 |= 0x00000001;   // Enable RxD1 //           

    U1LCR = UnLCR = uart_mode(mode); 
	
	U1DLL=(CPU_HZ/16/baud)%256;
	U1DLM=(CPU_HZ/16/baud)/256;

    U1LCR = UnLCR&0x7F;                 /* DLAB = 0                            */
    U1IER = 0x03;                       /* Enable RDA and THRE interrupts      */
 
    VICVectAddr7  = (unsigned int)int_uart1;
    VICVectCntl7  = 7;               /* Interrupt -> Priority */
    VICIntEnable |= (1 << 7);           /* Interrupt -> Enable   */

    memset((char *)&UART[1],0,sizeof(UART_PARM));
	UART[1].rx_buf=(unsigned char *)URX_BUFF+URX_LEN0+2;
    UART[1].tx_buf=(unsigned char *)UTX_BUFF+UTX_LEN0+2;
    UART[1].rx_max_buf=URX_LEN1;
    UART[1].tx_max_buf=UTX_LEN1;
    uart_rts_dis(1);
}
#endif

#ifdef UART2

void putch2(char c)
{
    while (!(U2LSR & 0x20));
    U2THR = c;
}

void int_uart2 (void) __irq 
{
    unsigned char c;

    if ((U2IIR & 0x0E) == 0x04) {        // Receive interrupt                   
       c = (char) U2RBR;                 // read character                      
       uart_rx_buf_write(2,c);
    }
                                         // Transmit interrupt  

	if (UART[2].tx_head!=UART[2].tx_tail) {
	   if ((U2LSR & 0x20))  U2THR=uart_tx_buf_read(2);
    }
	else {
	   if (UART[2].tx_int==1) UART[2].tx_int=2;
	}
    VICVectAddr = 0;                    // Acknowledge Interrupt   
}

void init_port2(int baud,char mode)
{
    unsigned char UnLCR;
    PCONP   |= 0x01000000; 
	PINSEL0 |= 0x00100000;  // Enable TxD2 //
	PINSEL0 |= 0x00400000;  // Enable RxD2 //   

    U2LCR = UnLCR = uart_mode(mode); 
	
	U2DLL=(CPU_HZ/16/baud)%256;
	U2DLM=(CPU_HZ/16/baud)/256;

    U2LCR = UnLCR&0x7F;                 /* DLAB = 0                            */
    U2IER = 0x03;                       /* Enable RDA and THRE interrupts      */
 
    VICVectAddr28  = (unsigned int)int_uart2;
    VICVectCntl28  = 28;               /* Interrupt -> Priority */
    VICIntEnable |= (1 << 28);             /* Interrupt -> Enable   */

    memset((char *)&UART[2],0,sizeof(UART_PARM));
	UART[2].rx_buf=(unsigned char *)URX_BUFF+URX_LEN0+2+URX_LEN1+2;
    UART[2].tx_buf=(unsigned char *)UTX_BUFF+UTX_LEN0+2+UTX_LEN1+2;
    UART[2].rx_max_buf=URX_LEN2;
    UART[2].tx_max_buf=UTX_LEN2;
    uart_rts_dis(2);
}
#endif



#ifdef UART3

void putch3(char c)
{
    while (!(U3LSR & 0x20));
    U3THR = c;
}

void int_uart3 (void) __irq 
{
    unsigned char c;

    if ((U3IIR & 0x0E) == 0x04) {        // Receive interrupt 
       c = (char) U3RBR;                 // read character                      
       uart_rx_buf_write(3,c);
    }
                                         // Transmit interrupt  
	if (UART[3].tx_head!=UART[3].tx_tail) {
	   if ((U3LSR & 0x20)) {
	       U3THR=uart_tx_buf_read(3);
	   }
    }
	else {
	   if (UART[3].tx_int==1) UART[3].tx_int=2;
	}
    VICVectAddr = 0;                    // Acknowledge Interrupt   
}

void init_port3(int baud,char mode)
{
    unsigned char UnLCR;
 
    PCONP   |= 0x02000000;
	PINSEL1 |= 0x000C0000;  // Enable TxD3 //
	PINSEL1 |= 0x00300000;  // Enable RxD3 //   

    U3LCR = UnLCR = uart_mode(mode); 
	
    U3DLL=(CPU_HZ/16/baud)%256;
	U3DLM=(CPU_HZ/16/baud)/256;
	
    U3LCR = UnLCR&0x7F;                 /* DLAB = 0                            */
    U3IER = 0x03;                       /* Enable RDA and THRE interrupts      */
 
    VICVectAddr29  = (unsigned int)int_uart3;
    VICVectCntl29  = 29;               /* Interrupt -> Priority */
    VICIntEnable |= (1 << 29);             /* Interrupt -> Enable   */

    memset((char *)&UART[3],0,sizeof(UART_PARM));
	UART[3].rx_buf=(unsigned char *)URX_BUFF+URX_LEN0+2+URX_LEN1+2+URX_LEN2+2;
    UART[3].tx_buf=(unsigned char *)UTX_BUFF+UTX_LEN0+2+UTX_LEN1+2+UTX_LEN2+2;
    UART[3].rx_max_buf=URX_LEN3;
    UART[3].tx_max_buf=UTX_LEN3;
    uart_rts_dis(3);
}
#endif


/////////////////////////////////////////////////////////////////

void uart_init_port(short ppath,int baud,char mode)
{
     switch(ppath) {
#ifdef UART0  
         case 0 : init_port0(baud,mode); break;
#endif  
#ifdef UART1
         case 1 : init_port1(baud,mode); break;
#endif  
#ifdef UART2
         case 2 : init_port2(baud,mode); break;
#endif  
#ifdef UART3
         case 3 : init_port3(baud,mode); break;
#endif  
     }
}

void uart_tx_clr_port(short ppath)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM) { 
	    UART[ppath].tx_head=0;
		UART[ppath].tx_tail=0; 
		UART[ppath].tx_int=0;
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) net_clr_tx_port(ppath);
#endif	 
}


void uart_tx_putch(short ppath,char ch)
{
    switch(ppath) {
#ifdef UART0	
        case 0: putch0(ch); break;
#endif	
#ifdef UART1		
        case 1: putch1(ch); break;
#endif	
#ifdef UART2		
        case 2: putch2(ch); break;
#endif	
#ifdef UART3		
        case 3: putch3(ch); break;
#endif	
#ifdef NET_FUN		
        default: if (ppath>=NET_SPATH) net_tx_buf_write(ppath,ch);
		         break;
#endif				
    }
}

unsigned short uart_tx_rdy(short ppath)
{
     if (ppath<0) return(0);
	 else if (ppath<UART_NUM) {	 
        if (UART[ppath].tx_head>=UART[ppath].tx_tail) return(UART[ppath].tx_head-UART[ppath].tx_tail);
        else return((UART[ppath].tx_head+UART[ppath].tx_max_buf)-UART[ppath].tx_tail);
	 }
#ifdef NET_FUN			
	 else if (ppath>=NET_SPATH) return(net_tx_buf_rdy(ppath));
#endif		 
	 else return(0);
}

unsigned char uart_tx_buf_read(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {
        if (UART[ppath].tx_tail >= UART[ppath].tx_max_buf) UART[ppath].tx_tail=0;
        return(UART[ppath].tx_buf[UART[ppath].tx_tail++]);
	}
#ifdef NET_FUN			
	else if (ppath>=NET_SPATH) return(net_tx_buf_read(ppath));
#endif	
	else return(0);
}

void  uart_tx_buf_write(short ppath,unsigned char c)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM)   {
	   if (!UART[ppath].tx_buf) return;	   
	   if (UART[ppath].tx_head>=UART[ppath].tx_max_buf) UART[ppath].tx_head=0;
       UART[ppath].tx_buf[UART[ppath].tx_head++]=c; 		   
	   while (uart_tx_rdy(ppath) >= (UART[ppath].tx_max_buf-1)) {
	      if (!UART[ppath].tx_int)  uart_tx_int_ena(ppath);
	   }	
	}
#ifdef NET_FUN			
	else if (ppath>=NET_SPATH) net_tx_buf_write(ppath,c);
#endif		
    else return;
}

void uart_tx_int_dis(short ppath)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM)   {
	   UART[ppath].tx_int=0; 
  //   for_delay(200);
	   uart_rts_dis(ppath);
	}
}

void uart_tx_int_ena(short ppath)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM)   {
	   if (UART[ppath].tx_int==1) return; 
	   if (uart_tx_rdy(ppath)>0) {
	       uart_rts_ena(ppath);
	       UART[ppath].tx_int=1; 
		   switch(ppath) {
		      case 0 :  U0THR=uart_tx_buf_read(ppath); break;
			  case 1 :  U1THR=uart_tx_buf_read(ppath); break;
			  case 2 :  U2THR=uart_tx_buf_read(ppath); break;
			  case 3 :  U3THR=uart_tx_buf_read(ppath); break;
		   }
       }
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) net_tx_int_ena(ppath);
#endif	

}

unsigned char uart_tx_int(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   return(UART[ppath].tx_int);
    else return(0);
}


unsigned char *uart_tx_buf(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   return(UART[ppath].tx_buf);
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) return(net_tx_buf(ppath));
#endif	
    else return(0);
}

unsigned short uart_tx_max(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   return(UART[ppath].tx_max_buf);
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) return(net_tx_max(ppath));
#endif	
	else return(0);
}

void uart_tx(short ppath,unsigned short dlen)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM) { 
	    UART[ppath].tx_head=dlen; UART[ppath].tx_tail=0; 
		uart_tx_int_ena(ppath);
	}
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) {
	    net_tx(ppath,dlen);
		uart_tx_int_ena(ppath);
	}
#endif	
}


////////////////////////////////////
void uart_rx_clr_port(short ppath)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM) { 
	    UART[ppath].rx_head=0;
		UART[ppath].rx_tail=0; 
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) net_clr_rx_port(ppath);
#endif	 
}

unsigned short uart_rx_rdy(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {
		if (UART[ppath].rx_head>=UART[ppath].rx_tail) return(UART[ppath].rx_head-UART[ppath].rx_tail);
        else return((UART[ppath].rx_head+UART[ppath].rx_max_buf)-UART[ppath].rx_tail);
	}
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) return(net_rx_buf_rdy(ppath));
#endif	
    return(0);
}

unsigned short uart_rx_max(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   return(UART[ppath].rx_max_buf);
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) return(net_rx_max(ppath));
#endif	
	else return(0);
}

unsigned char uart_rx_buf_read(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {
        if (UART[ppath].rx_tail >= UART[ppath].rx_max_buf) UART[ppath].rx_tail=0;
        return(UART[ppath].rx_buf[UART[ppath].rx_tail++]);
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) return(net_getch(ppath));
#endif		
	else return(0);
}

unsigned char uart_rx_buf_char(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {
        if (UART[ppath].rx_tail >= UART[ppath].rx_max_buf) UART[ppath].rx_tail=0;
        return(UART[ppath].rx_buf[UART[ppath].rx_tail]);
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) return(net_get_char(ppath));
#endif		
	else return(0);
}

void uart_rx_buf_write(short ppath,char c)
{
    if (ppath<0) return;
	else if (ppath<UART_NUM) {
	    if (!UART[ppath].rx_buf) return;	
        if (UART[ppath].rx_head>=UART[ppath].rx_max_buf) UART[ppath].rx_head=0;
        UART[ppath].rx_buf[UART[ppath].rx_head++]=c;
		UART[ppath].rxdly=0;
	}
#ifdef NET_FUN			
	else if (ppath>=NET_SPATH) net_rx_buf_write(ppath,c);
#endif		
}

unsigned char *uart_rx_buf(short ppath)
{
    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   return(UART[ppath].rx_buf);
#ifdef NET_FUN	
	else if (ppath>=NET_SPATH) return(net_rx_buf(ppath));
#endif	
    else return(0);
}



//////////////////////////////////////

void uart_rts_ena(short ppath)
{

}


void uart_rts_dis(short ppath)
{

}

unsigned char uart_protocol(short ppath)
{
#ifdef NET_FUN
    if (ppath>=NET_SPATH) return(net_protocol(ppath));
	else return(0);
#else	   
	return(0);
#endif	
}

unsigned char uart_pro(void)
{   
    unsigned char ret=0,ppath;
	for (ppath=0; ppath<UART_NUM; ppath++) {
	    if (UART[ppath].tx_int) { 
		    if ((uart_tx_rdy(ppath)<=0)&&(UART[ppath].tx_int==2)) uart_tx_int_dis(ppath); 
		}
	    else if (uart_tx_rdy(ppath)<=0) uart_rts_dis(ppath);
	    ret |= UART[ppath].tx_int;
    }
    return(ret);		
}

void dputstr(short ppath,char *s)
{
    unsigned short i;

    if (ppath<0) return;
	else if (ppath<UART_NUM) {	 
        i=0;
        while(s[i]!=0x0) {
            uart_tx_buf_write(ppath,s[i]);
            if (s[i]==0x0A) uart_tx_buf_write(ppath,0x0D);
            i++;
        }
	    uart_tx_int_ena(ppath);
	}	
#ifdef NET_FUN
	else if (ppath>=NET_SPATH) net_dputs(ppath,s);
#endif

}

unsigned short Pwrite(short ppath,unsigned char *s,unsigned short cnt)
{
    unsigned short i;

    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {    
        for (i=0; i<cnt; i++) uart_tx_buf_write(ppath,s[i]); 
		uart_tx_int_ena(ppath);
        return(i);
	}
#ifdef NET_FUN			
    else if (ppath>=NET_SPATH) {
	    for (i=0; i<cnt; i++) net_tx_buf_write(ppath,s[i]);
		uart_tx_int_ena(ppath);
        return(i);
	}
#endif	 
    else return(0);
}


unsigned short Pread(short ppath,unsigned char *s,unsigned short cnt)
{
    unsigned short i;

    if (ppath<0) return(0);
	else if (ppath<UART_NUM)   {    
        for (i=0; i<cnt; i++) s[i]=uart_rx_buf_read(ppath);
		return(i);
	}
#ifdef NET_FUN		
    else if (ppath>=NET_SPATH) {
	    for (i=0; i<cnt; i++) s[i]=net_getch(ppath);
		return(i);
	}
#endif	 
    else return(0);
}


void Dprintf(const char *fmt, ...)
{
	__va_list args;

    if (dpath<0) return;
	va_start(args, fmt);
	vsprintf(dmsg,fmt,args);
	va_end(args);
	dputstr(dpath,dmsg); 
	return;
}

void Pprintf(int ppath,const char *fmt, ...)
{
	__va_list args;

    if (ppath<0) return;
	va_start(args, fmt);
	vsprintf(dmsg,fmt,args);
	va_end(args);
	dputstr(ppath,dmsg); 
	return;
}

void Pputch(int ppath,char ch)
{
    if (ppath<0) return;  
	uart_tx_putch(ppath,ch);
}	

